#include "configdialog.h"
#include "ui_configdialog.h"

#include <QPushButton>
#include <QPixmap>
#include <QIcon>

#include <QDebug>

#include <QAbstractListModel>
#include <QStyledItemDelegate>
#include <QModelIndex>
#include <QLayoutItem>
#include <QVariant>
#include <QTabWidget>

#include "keypressfilter.h"

#include "core/core.h"
#include "settings/isettings.h"

const int g_categoryIconSize = 22;


class ConfigDialog::ConfigDialogPrivate{
public:
	ConfigDialogPrivate(){}

};



class ConfigDialog::Category{
public:
	QString m_name;
	QIcon m_icon;
	QTabWidget *m_pTabWidget;


	ISettings *m_pInterface;
};


class ConfigDialog::CategoryModel : public QAbstractListModel {
private:
	QIcon m_emptyIcon;

	QList<ConfigDialog::Category*> m_categories;
public:
	CategoryModel(QObject *parent = 0);
	~CategoryModel();

	int rowCount(const QModelIndex &parent = QModelIndex()) const;
	QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;

	void fillModel(const QList<ISettings*> &settings);

	QTabWidget *getPages( int row );
	ISettings *getInterface( int row );

	void restoreParents();
};


ConfigDialog::CategoryModel::CategoryModel(QObject *parent)
	: QAbstractListModel(parent)
{
	QPixmap empty( g_categoryIconSize, g_categoryIconSize );
	empty.fill( Qt::transparent );
	m_emptyIcon = QIcon( empty );
}

ConfigDialog::CategoryModel::~CategoryModel(){
	qDebug() << "kasuje model";
	qDeleteAll( m_categories );

}

int ConfigDialog::CategoryModel::rowCount(const QModelIndex &parent) const {
	return parent.isValid() ? 0 : m_categories.size();
}

QVariant ConfigDialog::CategoryModel::data(const QModelIndex &index,
										   int role) const
{
	switch( role ){
	case Qt::DisplayRole:
		return m_categories.at( index.row() )->m_name;
	case Qt::DecorationRole: {
			QIcon icon = m_categories.at( index.row() )->m_icon;
			if( icon.isNull() )
				icon = m_emptyIcon;
			return icon;
		}
	}

	return QVariant();
}

void ConfigDialog::CategoryModel::fillModel(const QList<ISettings*> &settings){
	// Clear any previous categories
	qDeleteAll(m_categories);
	m_categories.clear();

	// Put the pages in categories
	foreach(ISettings *page, settings) { //every ISetting has own category
		//TODO
		//make category shared; add page to TabWidget not create new category
		ConfigDialog::Category *category = new ConfigDialog::Category();
		category->m_name = page->category();
		category->m_icon = page->categoryIcon();
		category->m_pTabWidget = page->createPages();
		category->m_pInterface = page;

		if( category->m_icon.isNull() )
			category->m_icon = m_emptyIcon;

		m_categories.append(category);
	}
	reset();
}

QTabWidget* ConfigDialog::CategoryModel::getPages( int row ){
	if( row < 0 || row >= m_categories.count() )
		return NULL;

	return m_categories.at(row)->m_pTabWidget;
}

ISettings* ConfigDialog::CategoryModel::getInterface( int row ){
	if( row < 0 || row >= m_categories.count() )
		return NULL;

	return m_categories.at(row)->m_pInterface;
}

void ConfigDialog::CategoryModel::restoreParents(){
	foreach(ConfigDialog::Category* item, m_categories){
		item->m_pTabWidget->setParent( NULL );
	}
}


class ConfigDialog::CategoryDelegate : public QStyledItemDelegate
{
public:
	CategoryDelegate(QObject *parent = 0) : QStyledItemDelegate(parent) {}
	QSize sizeHint(const QStyleOptionViewItem &option,
				   const QModelIndex &index) const
	{
		QSize size = QStyledItemDelegate::sizeHint(option, index);
		size.setHeight(qMax(size.height(), 32));
		return size;
	}
};

//end of private classes
//------------------------------------------------------------------------------

ConfigDialog::ConfigDialog(QWidget *parent) :
    QDialog(parent),
	d(new ConfigDialog::ConfigDialogPrivate()),
	ui(new Ui::ConfigDialog)
{
    ui->setupUi(this);

	setWindowTitle( tr("Preferencje") );


	QPushButton *button = ui->buttonBox->button( QDialogButtonBox::Save );
	if( button ){
		QPixmap pixmap( ":/res/document-save.png" );
		button->setIcon( QIcon( pixmap ) );
		button->setIconSize( pixmap.size() );
	}

	button = ui->buttonBox->button( QDialogButtonBox::Cancel );
	if( button )
		button->setDefault( true );

	connect( this, SIGNAL(accepted()), this, SLOT(saveSettings()) );
	connect( this, SIGNAL(rejected()), this, SLOT(resetSettings()) );

	m_pModel = new ConfigDialog::CategoryModel(ui->listView);
	m_pDelegate = new ConfigDialog::CategoryDelegate(ui->listView);

	m_pModel->fillModel( Core::instance()->getSettingsPages() );
	ui->listView->setItemDelegate( m_pDelegate );
	ui->listView->setModel( m_pModel );
	ui->listView->setIconSize( QSize(g_categoryIconSize, g_categoryIconSize) );

	KeyPressFilter *kpf = new KeyPressFilter(ui->listView);
	ui->listView->installEventFilter( kpf );

	connect( ui->listView, SIGNAL(clicked(QModelIndex)),
			 this, SLOT(changeCategory(QModelIndex)) );

	connect( kpf , SIGNAL(enterPressed(QModelIndex)),
			 this, SLOT(changeCategory(QModelIndex)) );

	ui->listView->setCurrentIndex( m_pModel->index(0) );
	changeCategory( m_pModel->index(0) );
}

ConfigDialog::~ConfigDialog(){
	m_pModel->restoreParents();

	delete m_pModel;
	delete m_pDelegate;
	delete ui;

	qDebug() << "kasuje okno";
}


void ConfigDialog::changeCategory(QModelIndex index){
	const CategoryModel *model =
			dynamic_cast<const CategoryModel *>(index.model());

	QTabWidget *tab =
			const_cast<CategoryModel*>(model)->getPages( index.row() );

	QLayoutItem *item = ui->horizontalLayout_2->itemAt(1);
	if( item ){
		QWidget *tmp = item->widget();
		ui->horizontalLayout_2->removeWidget( tmp );
		tmp->setParent( NULL );
	}
	ui->horizontalLayout_2->addWidget( tab );
}

void ConfigDialog::saveSettings(){
	const QList<ISettings*> &lista = Core::instance()->getSettingsPages();
	foreach(ISettings *item, lista){
		item->save();
	}

	qDebug() << "save settings";
	emit closed();
	//very important for memory leaks, look at void SystemTray::showConfig()
}

void ConfigDialog::resetSettings(){
	const QList<ISettings*> &lista = Core::instance()->getSettingsPages();
	foreach(ISettings *item, lista){
		item->reset();
	}

	qDebug() << "reset settings";
	emit closed();
	//very important for memory leaks, look at void SystemTray::showConfig()
}
